#ifndef CONN_TAB_H
#define CONN_TAB_H
#include "fw5.h"
#include "network.h"
#include <linux/time.h>
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>
#include <linux/udp.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

#define FIVE_SECONDS 5
#define FIVE_MINUTES 60*FIVE_SECONDS
#define KEEP_TIME -1		 // keep current value of expires
#define RESET_TIME 0		 // set time to 0
#define NUM_OF_STATES 4		 // number of defined tcp states  
#define CONV_NOT_FOUND NULL  // connection was not found	
#define CONN_TABLE_FULL NULL // connection table is full
#define CONV_EXPIRED -2		 // found conversation has expired
#define BAD_STATE -1		 // undefined tcp state 
#define BAD_COMMAND -1		 // undefined combination of flags from packet

// sides of conversation
typedef enum{
	CLIENT = 0,
	SERVER = 1,
	BOTH = 2,
} side_t;

// cell of tcp state machine
typedef struct{	
	int nextState;  // next state of conversation	
	int side; 		// current valid side of conversation
	int seconds;	// time for updating expiration time 
} cell_t;

// commads of tcp state machine
// represent valid combinations of tcp flags
typedef enum{
	NONE = 0,
	SYN = 1,
	ACK = 2,
	SYN_ACK = 3,	
	FIN = 4,	
	FIN_SYN = 5,
	FIN_ACK = 6,
	FIN_SYN_ACK = 7,
	RESET = 8,	
	NUM_OF_COMMANDS = 9,	
} tcp_commands_t;  


/*
 * function findConversation
 * searches for a saved connection in the connection table by ips and ports. 
 * if it finds an expired connection, continues the search through the table for an active one    
 * returns a pointer to the connection if found and not expired yet, CONV_NOT_FOUND - otherwise
 * params: pointer to a rawPacket, which contains all info about the packet  
 */
connection_t* findConversation(rawPacket_t* packet);

/*
 * function setState
 * updates the state and expiration time of a connection according to 
 * the tcp state machine, previous state and the command   
 * params: pointer to the connection that needs update, the new state to set and the command
 */  
void setState(connection_t* conv, tcp_conn_t state,tcp_commands_t command);

/*
 * function addConversation
 * adds a new connection to the connection table 
 * searches for an empty slot in the connection table and if found,
 * creates a new connection with the TCP_SYN_SENT state and expiration time of now() + 5 seconds
 * params: pointer to the rawPacket which has all info about the packet 
 * returns a pointer to the new connection if there is a place, CONN_TABLE_FULL - otherwise  
 */ 
connection_t* addConversation(rawPacket_t* packet);

/*
 * function nextState
 * checks with the tcp state machine whether there is a valid state next
 * state for connection to go to from its current state, the command and the side
 * params: current state of connection, the recived command and the side of the connection
 * returns the next tcp state if params are valid and side matches, BAD_STATE - otherwise  
 */ 
tcp_conn_t nextState(tcp_conn_t currentState, tcp_commands_t command, side_t side);

/*
 * function getCommand
 * commputes the tcp machine command from the tcp flags of the recieved packet 
 * params: the tcpHeaderParams_t struct which contains info about the tcp header
 * returns a tcp_commands_t command if flags combination is valid, BAD_COMMAND - otherwise
 */ 
tcp_commands_t getCommand(tcpHeaderParams_t params);

/*
 * function clearConnectionTable
 * clears all the memory of the connection table by setting it to 0 
 */ 
void clearConnectionTable(void);

/*
 * function initStateMachine
 * fills all the cells of the tcp state machine with their values
 * it creates all the states and the transitions of the machine
 * must be called before the tcp track begins
 */ 
void initStateMachine(void);

/*
 * function printConversationTable
 * prints the connection table in a nice format
 * for debuging
 */
void printConversationTable(void);


/*
 * function numOfConversations
 * counts the number of current active conversations 
 * for debuging
 */
int numOfConversations(void);
#endif

